/**
 * 
 */
package br.com.sistransporte.transite.ponto.dao;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;

import org.hibernate.Query;
import org.hibernate.Session;

import br.com.sistransporte.transitevo.linha.model.LinhaVO;
import br.com.sistransporte.transitevo.ponto.model.PontoVO;
import br.com.src.masterpersistence.dao.GenericDAO;
import br.com.src.masterpersistence.exceptions.AlterarException;
import br.com.src.masterpersistence.exceptions.ExcluirException;
import br.com.src.masterpersistence.exceptions.FiltrarException;
import br.com.src.masterpersistence.exceptions.HibernatePersistenceException;
import br.com.src.masterpersistence.exceptions.InserirException;
import br.com.src.masterpersistence.utilidades.FabricaMensagensLog;
import br.com.src.masterpersistence.utilidades.Paginacao;
import br.com.src.utilidades.exceptions.DesconhecidoException;

/**
 * Classe que representa
 *
 *
 * @author Nelson Luis da Silva Junior <nelson.jr13@hotmail.com@>
 * @since 5 de Jul de 2013 00:52:08
 * @version 1.0
 */
public class PontoDAOImpl extends GenericDAO< PontoVO > implements PontoDAOService{

	public PontoDAOImpl(String typeSessionFactory) {
		super(typeSessionFactory);
		logger.info( FabricaMensagensLog.getMensagemLogConstrutor("PontoDAOImpl") );
	}

	
	public ArrayList<PontoVO> filtrar(PontoVO vo, boolean isDisticnt,boolean isLike) throws FiltrarException {
		logger.info( FabricaMensagensLog.getMensagemLogInicio("PontoDAOImpl") );
		try {
			ArrayList< PontoVO > lista = filter( vo, isDisticnt, isLike );
			logger.info( FabricaMensagensLog.getMensagemLogTermino( "PontoDAOImpl" ) );
			return lista;
		} catch ( IllegalArgumentException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro("PontoDAOImpl", e ) );
			throw new FiltrarException( e.getMessage(), e );
		} catch ( IllegalAccessException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", e ) );
			throw new FiltrarException( e.getMessage(), e );
		} catch ( InvocationTargetException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", e ) );
			throw new FiltrarException( e.getMessage(), e );
		} catch ( Exception e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", new DesconhecidoException( e.getMessage(), e ) ) );
			throw new FiltrarException( e.getMessage(), e );
		}
	}
	
	@SuppressWarnings( "unchecked" )
    public ArrayList<PontoVO> listarPontosComLinha(LinhaVO vo) throws FiltrarException {
		logger.info( FabricaMensagensLog.getMensagemLogInicio("PontoDAOImpl") );
		
		Session session = getSessaoAberta();
		try {

			Query query = session.createQuery("SELECT p FROM PontoVO p WHERE p.id "+
					"IN (SELECT lp.ponto.id FROM LinhaPontoVO lp "+
					"WHERE lp.linha.id = :codigo)");
			query.setInteger("codigo", vo.getId());
			
			ArrayList< PontoVO > listaPontos = (ArrayList< PontoVO >) query.list();
			
			return listaPontos;
		} catch ( IllegalArgumentException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro("PontoDAOImpl", e ) );
			throw new FiltrarException( e.getMessage(), e );
		} catch ( Exception e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", new DesconhecidoException( e.getMessage(), e ) ) );
			throw new FiltrarException( e.getMessage(), e );
		} finally {
			session.close();
		}
	}
	
	@SuppressWarnings( "unchecked" )
    public ArrayList<PontoVO> listarPontosSemLinha(LinhaVO vo) throws FiltrarException {
		logger.info( FabricaMensagensLog.getMensagemLogInicio("PontoDAOImpl") );
		Session session = getSessaoAberta();
		try {
			
			Query query = session.createQuery("SELECT p FROM PontoVO p WHERE p.id "+
											"NOT IN (SELECT lp.ponto.id FROM LinhaPontoVO lp "+
											"WHERE lp.linha.id = :codigo)");
			query.setInteger("codigo", vo.getId());
			
			ArrayList< PontoVO > listaPontos = (ArrayList< PontoVO >) query.list();
			
			return listaPontos;
		} catch ( IllegalArgumentException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro("PontoDAOImpl", e ) );
			throw new FiltrarException( e.getMessage(), e );
		} catch ( Exception e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", new DesconhecidoException( e.getMessage(), e ) ) );
			throw new FiltrarException( e.getMessage(), e );
		} finally {
			session.close();
		}
	}
	
	public PontoVO obterPontoOrigem(LinhaVO vo)throws FiltrarException {
		logger.info(FabricaMensagensLog.getMensagemLogInicio("PontoDAOImpl"));
		
		Session session = getSessaoAberta();
		
		try {
			Query query = session.createQuery("SELECT p FROM LinhaPontoVO lp INNER JOIN lp.ponto p WHERE lp.linha.id = :idLinha AND lp.ordemParada = (SELECT MIN(lp.ordemParada) FROM LinhaPontoVO lp WHERE lp.linha.id = :idLinha)");
			query.setInteger("idLinha", vo.getId());

			return (PontoVO) query.uniqueResult();

		} catch (IllegalArgumentException e) {logger.info(FabricaMensagensLog.getMensagemLogErro("PontoDAOImpl",e));
			throw new FiltrarException(e.getMessage(), e);
		} catch (Exception e) {
			logger.info(FabricaMensagensLog.getMensagemLogErro("PontoDAOImpl",new DesconhecidoException(e.getMessage(), e)));
			throw new FiltrarException(e.getMessage(), e);
		} finally {
			session.close();
		}
	}
	
	public PontoVO obterPontoDestino(LinhaVO vo)throws FiltrarException {
		logger.info(FabricaMensagensLog.getMensagemLogInicio("PontoDAOImpl"));
		
		Session session = getSessaoAberta();
		
		try {

			Query query = session.createQuery("SELECT p FROM LinhaPontoVO lp INNER JOIN lp.ponto p WHERE lp.linha.id = :idLinha AND lp.ordemParada = (SELECT MAX(lp.ordemParada) FROM LinhaPontoVO lp WHERE lp.linha.id = :idLinha)");
			query.setInteger("idLinha", vo.getId());

			return (PontoVO) query.uniqueResult();

		} catch (IllegalArgumentException e) {logger.info(FabricaMensagensLog.getMensagemLogErro("PontoDAOImpl",e));
			throw new FiltrarException(e.getMessage(), e);
		} catch (Exception e) {
			logger.info(FabricaMensagensLog.getMensagemLogErro("PontoDAOImpl",new DesconhecidoException(e.getMessage(), e)));
			throw new FiltrarException(e.getMessage(), e);
		} finally {
			session.close();
		}
	}
	
	public PontoVO inserir(PontoVO vo) throws InserirException {
		try {
			logger.info( FabricaMensagensLog.getMensagemLogInicio( "PontoDAOImpl" ) );
			PontoVO objetoPersistido = (PontoVO) insert( vo );
			logger.info( FabricaMensagensLog.getMensagemLogTermino( "PontoDAOImpl" ) );
			return objetoPersistido;
		} catch ( HibernatePersistenceException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", e ) );
			throw new InserirException( e.getMessage(), e );
		}
	}

	
	public void alterar(PontoVO vo) throws AlterarException {
		logger.info( FabricaMensagensLog.getMensagemLogInicio( "PontoDAOImpl" ) );
		try {
			update( vo );
		} catch ( HibernatePersistenceException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro("PontoDAOImpl", e ) );
			throw new AlterarException( e.getMessage(), e );
		}
		logger.info( FabricaMensagensLog.getMensagemLogTermino("PontoDAOImpl" ) );
	    
		
	}

	
	public void excluir(PontoVO vo) throws ExcluirException {
		logger.info( FabricaMensagensLog.getMensagemLogInicio( "PontoDAOImpl" ) );
		try {
			delete( vo );
		} catch ( HibernatePersistenceException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", e ) );
			throw new ExcluirException( e.getMessage(), e );
		}
		logger.info( FabricaMensagensLog.getMensagemLogTermino( "PontoDAOImpl" ) );
	}

	
	public ArrayList<PontoVO> filtrarPaginacao(Paginacao<PontoVO> pagination, PontoVO vo, boolean isDisticnt,	boolean isLike) throws FiltrarException {
		logger.info( FabricaMensagensLog.getMensagemLogInicio( "PontoDAOImpl" ) );
		try {
			ArrayList< PontoVO > lista = paginacao( pagination, vo, isDisticnt, isLike );
			logger.info( FabricaMensagensLog.getMensagemLogTermino( "PontoDAOImpl" ) );
			return lista;
		} catch ( IllegalArgumentException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", e ) );
			throw new FiltrarException( e.getMessage(), e );
		} catch ( IllegalAccessException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", e ) );
			throw new FiltrarException( e.getMessage(), e );
		} catch ( InvocationTargetException e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", e ) );
			throw new FiltrarException( e.getMessage(), e );
		} catch ( Exception e ) {
			logger.info( FabricaMensagensLog.getMensagemLogErro( "PontoDAOImpl", new DesconhecidoException( e.getMessage(), e ) ) );
			throw new FiltrarException( e.getMessage(), e );
		}
		
	}
	
	@Override
    public Integer getTotalCadastrados( PontoVO entidade, boolean isDisticnt, boolean isLike ) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		return super.getTotalCadastrados( entidade, isDisticnt, isLike );
	    
    }
}
